﻿if (!_9GG) {
    var _9GG = (function () {
        //用于引用对象复制
        function clone(obj) {
            function Fn() { }
            Fn.prototype = obj;
            var o = new Fn();
            for (var a in o) {
                if (typeof o[a] == "object") {
                    o[a] = clone(o[a]);
                }
            }
            return o;
        }
        //9宫格解析
        function lxwParse(arr) {


            //初始化需要排列的对象数组
            var ARR = [];
            for (var k2 in arr)
                for (var i2 = 0; i2 < arr[k2]; i2++)
                    ARR.push(k2);

            //复制一个临时对象数组
            var ARRCOPY = ARR.concat();

            //用于存储每个对象的id,list,w，h
            //list代表他的占用的格子坐标,w代表对象占x方向的格子数量，h代表对象占y方向格子的数量
            var lstStore = [];

            //用于给对象编号
            var count = 0;
            //最多排列三行
            var rows = 3;
            //起始列的索引，都是从0开始排列
            var cols = 0;
            //存储格子是否被占用
            var _ = {};


            //11可以变成22,33
            //21可以变成42,63
            //31可以变成62,93
            //12和13都不能再放大了，因为我们最多只有三行
            //先只考虑11的变形情况，最终变形完毕的格子能被3整除最好

            //根据需要，把Ax变成Ay，比如把a11变形为a22或者a33
            function change(_arr, old, _new, count) {
                for (var m = 0; m < _arr.length && count > 0; m++) {
                    if (_arr[m] == old) {
                        _arr[m] = _new;
                        count--;
                    }
                }
            }

            //得到对象占用的空间 a11代表一个格子，a23代表6个格子
            function getlength(_arr) {
                var count = 0;
                for (var m = 0; m < _arr.length; m++) {
                    var t = _arr[m];
                    count += parseInt(t[1]) * parseInt(t[2]);
                }

                return count;
            }

            //只考虑a11的情况放大，其他情况不考虑
            function checkArr() {
                var a11count = parseInt(arr.a11);
                var a31count = parseInt(arr.a31);

                //for(var j=0;j<a31count;j++){
                //	var arr = TEMP.concat();
                //	change(arr,"a31","a93",(j+1));

                for (var m = 0; m <= a11count; m++) {
                    var _arr = ARRCOPY.concat();
                    change(_arr, "a11", "a33", m);

                    //m个变成4
                    for (var n = 0; n <= a11count - m; n++) {
                        //n个变成9
                        change(_arr, "a11", "a22", n);

                        if (getlength(_arr) % 3 == 0) {
                            ARRCOPY = _arr.concat();
                            return true;
                        }
                    }
                }
                //}

                return false;
            }

            //单独处理a31,a12,a21的情况，全部是他们，显示效果比较特殊。没有任何组合的时候
            if (ARRCOPY.length == arr.a31) {
                for (var m = 0; m < ARRCOPY.length; m++) {
                    lstStore[count++] = { id: "a31", list: [(m * 3) + "," + 0], w: 3, h: 3 };
                }
                return lstStore;
            }

            if (ARRCOPY.length == arr.a21) {
                for (var m = 0; m < ARRCOPY.length; m++) {
                    lstStore[count++] = { id: "a21", list: [m * 6 + "," + 0], w: 6, h: 3 };
                }
                return lstStore;
            }

            if (ARRCOPY.length == arr.a12) {
                for (var m = 0; m < ARRCOPY.length; m++) {
                    lstStore[count++] = { id: "a12", list: [m * 2 + "," + 0], w: 2, h: 3 };
                }
                return lstStore;
            }

            //整体数量小于4的时候，全部用最大容器存储
            if (ARRCOPY.length <= 4) {
                var c = 0;
                for (var k = 0; k < ARRCOPY.length; k++) {
                    var a = ARRCOPY[k];
                    if (a == "a31") {
                        lstStore[count++] = { id: a, list: [c + "," + 0], w: 3, h: 3 };
                        c += 3;
                    }

                    if (a == "a21") {
                        lstStore[count++] = { id: a, list: [c + "," + 0], w: 6, h: 3 };
                        c += 6;
                    }

                    if (a == "a12") {
                        lstStore[count++] = { id: a, list: [c + "," + 0], w: 2, h: 3 };
                        c += 2;
                    }
                    if (a == "a11") {
                        lstStore[count++] = { id: a, list: [c + "," + 0], w: 3, h: 3 };
                        c += 3;
                    }
                    if (a == "a13") {
                        lstStore[count++] = { id: a, list: [c + "," + 0], w: 1, h: 3 };
                        c += 1;
                    }
                }

                return lstStore;
            }

            if (!checkArr()) {
                console.log("找不到最好的比例，应该不会存在？");
            }
            //占用1个格子
            function addnode1(a, v1, w, h) {
                _[v1] = 1;
                lstStore[count++] = { id: a, list: [v1], w: w, h: h };
            }
            //占用2个格子
            function addnode2(a, v1, v2, w, h) {
                _[v1] = 1;
                _[v2] = 1;
                lstStore[count++] = { id: a, list: [v1, v2], w: w, h: h };
            }
            //占用3个格子
            function addnode3(a, v1, v2, v3, w, h) {
                _[v1] = 1;
                _[v2] = 1;
                _[v3] = 1;
                lstStore[count++] = { id: a, list: [v1, v2, v3], w: w, h: h };
            }
            //占用4个格子
            function addnode4(a, v1, v2, v3, v4, w, h) {
                _[v1] = 1;
                _[v2] = 1;
                _[v3] = 1;
                _[v4] = 1;
                lstStore[count++] = { id: a, list: [v1, v2, v3, v4], w: w, h: h };
            }
            //占用9个格子
            function addnode9(a, v1, v2, v3, v4, v5, v6, v7, v8, v9, w, h) {
                _[v1] = 1;
                _[v2] = 1;
                _[v3] = 1;
                _[v4] = 1;
                _[v5] = 1;
                _[v6] = 1;
                _[v7] = 1;
                _[v8] = 1;
                _[v9] = 1;
                lstStore[count++] = { id: a, list: [v1, v2, v3, v4, v5, v6, v7, v8, v9], w: w, h: h };
            }
            //占用27个格子
            function addnode93(a, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, w, h) {
                _[v1] = 1; _[v2] = 1; _[v3] = 1; _[v4] = 1; _[v5] = 1; _[v6] = 1; _[v7] = 1; _[v8] = 1; _[v9] = 1;
                _[v11] = 1; _[v12] = 1; _[v13] = 1; _[v14] = 1; _[v15] = 1; _[v16] = 1; _[v17] = 1; _[v18] = 1; _[v19] = 1;
                _[v21] = 1; _[v22] = 1; _[v23] = 1; _[v24] = 1; _[v25] = 1; _[v26] = 1; _[v27] = 1; _[v10] = 1; _[v20] = 1;

                lstStore[count++] = {
                    id: a, list: [v1, v2, v3, v4, v5, v6, v7, v8, v9,
                      v10, v11, v12, v13, v14, v15, v16, v17, v18,
                      v19, v20, v21, v22, v23, v24, v25, v26, v27], w: w, h: h
                };
            }

            //a插入的对象
            //c插入的位置 x坐标
            //r插入的位置 y坐标
            function insert(a, c, r) {
                if (a == "a11") {
                    addnode1(a, addc(c) + "," + r, 1, 1);
                    return true;
                }

                if (a == "a22") {
                    if (r > 1
                    || _[(c + 1) + "," + (r + 0)] === 1
                    || _[(c + 0) + "," + (r + 1)] === 1
                    || _[(c + 1) + "," + (r + 1)] === 1
                    )
                        return false;

                    addnode4(a,
                    addc(c) + "," + r,
                    addc(c + 1) + "," + r,
                    addc(c) + "," + (r + 1),
                    addc(c + 1) + "," + (r + 1),

                    2, 2);
                    return true;
                }

                if (a == "a33") {
                    //代表9个格子没有任何东西
                    if (r > 0
                    || _[(c + 0) + "," + (r + 0)] === 1//已经判断过
                    || _[(c + 0) + "," + (r + 1)] === 1
                    || _[(c + 0) + "," + (r + 2)] === 1
                    || _[(c + 1) + "," + (r + 0)] === 1
                    || _[(c + 1) + "," + (r + 1)] === 1
                    || _[(c + 1) + "," + (r + 2)] === 1
                    || _[(c + 2) + "," + (r + 0)] === 1
                    || _[(c + 2) + "," + (r + 1)] === 1
                    || _[(c + 2) + "," + (r + 2)] === 1
                    )
                        return false;

                    addnode9(a,
                    addc(c) + "," + (r + 0),
                    addc(c) + "," + (r + 1),
                    addc(c) + "," + (r + 2),

                    addc(c + 1) + "," + (r + 0),
                    addc(c + 1) + "," + (r + 1),
                    addc(c + 1) + "," + (r + 2),

                    addc(c + 2) + "," + (r + 0),
                    addc(c + 2) + "," + (r + 1),
                    addc(c + 2) + "," + (r + 2),


                    3, 3);
                    return true;
                }

                if (a == "a21") {
                    if (_[(c + 1) + "," + r] === 1)
                        return false;

                    addnode2(a, addc(c) + "," + r, addc(c + 1) + "," + r, 2, 1);
                    return true;
                }

                if (a == "a31") {
                    if (_[(c + 1) + "," + r] === 1 || _[(c + 2) + "," + r] === 1)
                        return false;
                    addnode3(a, addc(c) + "," + r, addc(c + 1) + "," + r, addc(c + 2) + "," + r, 3, 1);
                    return true;
                }

                if (a == "a12") {
                    if (r > 1 || _[c + "," + (r + 1)] === 1)
                        return false;
                    addnode2(a, addc(c) + "," + r, addc(c) + "," + (r + 1), 1, 2);
                    return true;
                }
                if (a == "a13") {
                    if (r > 0 || _[c + "," + (r + 1)] === 1 || _[c + "," + (r + 2)] === 1)
                        return false;
                    addnode3(a, addc(c) + "," + r, addc(c) + "," + (r + 1), addc(c) + "," + (r + 2), 1, 3);
                    return true;
                }
            }

            //设置目前最新的列
            function addc(c) {
                cols = Math.max(cols, c);
                return c;
            }

            //返回x,y字符串
            function poi(x, y) {
                return x + "," + y;
            }

            //返回x,y格子里面是否存在被占用
            function _poi(x, y) {
                return _[x + "," + y];
            }

            //查找该格子是否被其他对象占用
            function findo(c, r) {
                for (var k = 0; k < lstStore.length; k++) {
                    var arr = lstStore[k];
                    for (var m = 0; m < arr.list.length; m++) {
                        if (arr.list[m] == poi(c, r))
                            return arr;
                    }
                }

                return null;
            }

            //判断该格子是否属于自己
            function findmy(arr, cr) {
                for (var m = 0; m < arr.length; m++) {
                    if (arr[m] == cr)
                        return true;
                }

                return false;
            }

            //判断对象是否能够左右移动
            function rightleft(o, f) {
                for (var m = 0; m < o.list.length; m++) {
                    var c = parseInt(o.list[m].split(',')[0]) + f;
                    var r = parseInt(o.list[m].split(',')[1]);

                    if (_[poi(c, r)] === 1 && !findmy(o.list, poi(c, r)))
                        return false;
                }

                var len = o.list.length;
                //代表可以移动
                for (var m = 0; m < len; m++) {
                    var c = parseInt(o.list[m].split(',')[0]) + f;
                    var r = parseInt(o.list[m].split(',')[1]);

                    if (_poi(c, r) === 1) continue;
                    //设置上点被占用
                    _[poi(c, r)] = 1;
                    o.list.push(poi(c, r));
                }
                o.w += f;

                return true;
            }

            //上下
            function topbottom(o, f) {
                for (var m = 0; m < o.list.length; m++) {
                    var c = parseInt(o.list[m].split(',')[0]);
                    var r = parseInt(o.list[m].split(',')[1]) + f;

                    if (_[poi(c, r)] === 1 && !findmy(o.list, poi(c, r)))
                        return false;
                }

                var len = o.list.length;
                //代表可以移动
                for (var m = 0; m < len; m++) {
                    var c = parseInt(o.list[m].split(',')[0]);
                    var r = parseInt(o.list[m].split(',')[1]) + f;

                    if (_poi(c, r) === 1) continue;
                    //设置上点被占用
                    _[poi(c, r)] = 1;
                    o.list.push(poi(c, r));
                }
                o.h += f;

                return true;
            }

            //处理对象的上下左右的空格情况
            function other(o) {
                //代表已经被别人填充
                if (_[o] === 1) return true;
                //c-1
                var c = parseInt(o.split(',')[0]);
                var r = parseInt(o.split(',')[1]);

                var tmp = 0;

                tmp = r - 1;
                if (tmp >= 0) {
                    if (_poi(c, tmp) === 1) {
                        var target = findo(c, tmp);
                        if (topbottom(target, 1))
                            return true;
                    }
                }

                tmp = c - 1;
                if (tmp >= 0) {
                    if (_poi(tmp, r) === 1) {
                        var target = findo(tmp, r);
                        if (rightleft(target, 1))
                            return true;
                    }
                }

                tmp = r + 1;
                if (tmp <= rows) {
                    if (_poi(c, tmp) === 1) {
                        var target = findo(c, tmp);
                        if (topbottom(target, -1))
                            return true;
                    }
                }

                tmp = c + 1;
                if (tmp <= cols) {
                    if (_poi(tmp, r) === 1) {
                        var target = findo(tmp, r);
                        if (rightleft(target, -1))
                            return true;
                    }
                }

                //这里是否可能不太确定？
                console.log("这里是否可能不太确定？" + o);
                return false;
            }

            //每次循环都必须初始化参数
            function init() {
                lstStore = [];
                count = 0;
                rows = 3;
                cols = 0;
                _ = {};
                ARR = ARRCOPY.concat();
            }


            //最多随机运行50次，如果50次中发现最好的机会，就停止，否则就用50次中空格最少的组合。
            var MAX = 50;

            //未填词剩余格子数量
            var result = [];

            //临时存储已经填充的格子
            var tmpLst = {};
            //临时存储对象的分布情况
            var tmpStore = [];

            while (MAX-- > 0) {
                init();
                while (1) {
                    if (ARR.length == 0) break;

                    var index = parseInt(ARR.length * Math.random());
                    var a = ARR[index];


                    //查找容器里面哪里有没有数据，然后判断数据是否能够放的下
                    var c = 0;
                    var r = 0;

                    while (1) {
                        if (ARR.length == 0) break;
                        if (_[c + "," + r] === 1) {
                            r++;
                            if (r % rows == 0) {
                                r = 0;
                                c++;
                                continue;
                            }
                        } else {
                            //代表有空，他的右侧不知道是否有空
                            //能不能插入，插入到哪里
                            if (insert(a, c, r)) {
                                //移除
                                ARR.splice(index, 1);
                                break;
                            }
                            else {
                                r++;
                                if (r % rows == 0) {
                                    r = 0;
                                    c++;
                                    continue;
                                }
                            }
                        }
                    }
                }

                //判断还存在空格，然后进行周围扩充
                console.log(">>>>>>>>>>>>" + cols);
                var cc = 0;
                var tmpResult = [];

                while (cc <= cols) {
                    for (var r = 0; r < rows; r++) {
                        if (!(_[cc + "," + r] === 1)) {
                            tmpResult.push(cc + "," + r);
                            console.log(cc + "," + r);
                        }
                    }
                    cc++;
                }

                if (result.length == 0) {
                    tmpStore = lstStore.concat();
                    tmpLst = clone(_);
                    result = tmpResult.concat();
                }
                else {
                    if (tmpResult.length < result.length) {
                        tmpStore = lstStore.concat();
                        tmpLst = clone(_);
                        result = tmpResult.concat();
                    }
                }

                //最佳组合
                if (result.length == 0) break;
            }

            //把最佳组合的信息还原给全局变量
            lstStore = tmpStore;
            _ = tmpLst;

            //排列出来不一定是最优的结果。
            //__里面就是排列的对象，就是符合要求的。
            if (result.length == 0) {
                console.log("全部符合要求");
                for (var o in lstStore) {
                    console.log(lstStore[o].id + ">" + lstStore[o].list.join("|") + ">" + lstStore[o].w + "," + lstStore[o].h);
                }
            }
            else {
                //把已经完成的格子循环出来
                console.log("补充格子之前");
                for (var o in lstStore) {
                    console.log(lstStore[o].id + ">" + lstStore[o].list.join("|") + ">" + lstStore[o].w + "," + lstStore[o].h);
                }

                //result 里面是没有被填充的对象，是需要考虑变形放大处理
                //排列顺序总是从上到下，从左到右
                console.log("空格个数" + result.length);
                for (var k = 0; k < result.length; k++) {
                    var o = result[k];
                    console.log(o);
                }

                console.log("开始进行补充格子");
                for (var k = 0; k < result.length; k++) {
                    var o = result[k];
                    other(o);
                }

                console.log("补充格子之后");
                for (var o in lstStore) {
                    console.log(lstStore[o].id + ">" + lstStore[o].list.join("|") + ">" + lstStore[o].w + "," + lstStore[o].h);
                }
            }

            return lstStore;
        }
        return {parse:lxwParse};
    })();
}